#include "tabcontrol.h"

WNDPROC TabControl::_originalWndProc = NULL;

TabControl::Tab::~Tab()
{
}

TabControl::TabControl()
{
	_hWnd = NULL;
}

TabControl::~TabControl()
{
	if( IsWindow( _hWnd ) )
	{
		//Detach the instance from this window and destroy the window.
		SetWindowLongPtr( _hWnd, GWLP_USERDATA, NULL );
		DestroyWindow( _hWnd );
	}
}

bool TabControl::create( HWND hWndParent, HINSTANCE hInstance )
{
	if( _originalWndProc == NULL )
	{
		//The TabControl might not been loaded yet.
		INITCOMMONCONTROLSEX initCtrls;
		initCtrls.dwSize = sizeof( INITCOMMONCONTROLSEX );
		initCtrls.dwICC = ICC_TAB_CLASSES;
		if( InitCommonControlsEx( &initCtrls ) == false )
		{
			//Error loading the tab classes.
			return false;
		}
	}

	_hWnd = CreateWindowEx(
		0, //dwExStyle
		(LPCWSTR) WC_TABCONTROL, //lpClassName
		L"", //lpWindowName
		WS_CHILD, //dwStyle
		10, //X
		10, //Y
		200, //nWidth
		100, //nHeight
		hWndParent, //hWndParent
		NULL, //hMenu
		hInstance, //hInstance
		NULL //lpParam
		);
	if( _hWnd == NULL )
	{
		return false;
	}

	//Subclass the window. Subclassing is the name of a win32 technique to change the
	//behaviour of a type of window (the class) by changing it's message handling function.
	_originalWndProc = (WNDPROC) SetWindowLongPtr( _hWnd, GWLP_WNDPROC, (LONG_PTR) Window::ooDispatcher );

	//Store a pointer to this instance by the window.
	SetWindowLongPtr( _hWnd, GWLP_USERDATA, (LONG_PTR) this );
	return true;
}

int TabControl::addTab( LPWSTR text, Tab *obj, unsigned int index )
{
	// Return the index of the new tab, -1 on error.

	TCITEM tab;
	tab.mask = TCIF_TEXT | TCIF_PARAM; //Set the text and parameter.
	tab.pszText = text; //The text on the tab.
	tab.lParam = (LPARAM) obj; //The parameter (a pointer to the Tab instance).
	return (int) SendMessage( _hWnd, TCM_INSERTITEM, (WPARAM) index, (LPARAM) &tab );
}

int TabControl::currentTab()
{
	return (int) SendMessage(
		_hWnd,
		TCM_GETCURSEL,
		(WPARAM) 0,
		(LPARAM) 0
		);
}

int TabControl::setCurrentTab( int tab )
{
	//Return the index of the previously selected tab, -1 on error.

	return (int) SendMessage(
		_hWnd,
		TCM_SETCURSEL,
		(WPARAM) tab,
		(LPARAM) 0
		);
}

bool TabControl::closeTab( int tab )
{
	//This does not delete the Tab instance.
	return SendMessage(
		_hWnd,
		TCM_DELETEITEM,
		(WPARAM) tab,
		(LPARAM) 0
		) != 0;
}

TabControl::Tab* TabControl::getTab( int tab )
{
	TCITEM item;
	item.mask = TCIF_PARAM; //Request the parameter only.
	if( SendMessage(
		_hWnd,
		TCM_GETITEM,
		(WPARAM) tab,
		(LPARAM) &item
		) == FALSE )
	{
		return NULL;
	}
	//lParam contains the pointer to the Tab instance.
	return (Tab*) item.lParam;
}

BOOL TabControl::setPosition( RECT rect, BOOL repaint )
{
	return MoveWindow(
		_hWnd,
		rect.left,
		rect.top,
		rect.right - rect.left,
		rect.bottom - rect.top,
		repaint
		);
}

void TabControl::show( int nCmdShow )
{
	ShowWindow( _hWnd, nCmdShow );
}

unsigned int TabControl::tabCount()
{
	return (unsigned int) SendMessage(
		_hWnd,
		TCM_GETITEMCOUNT,
		(WPARAM) 0,
		(LPARAM) 0
		);
}

LRESULT TabControl::handleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	//Handle messages for the tabcontrol here. Note that some messages are send to the
	//parent.

	if( _originalWndProc )
		return _originalWndProc( _hWnd, uMsg, wParam, lParam );
	else
		return DefWindowProc( _hWnd, uMsg, wParam, lParam );
}

HWND TabControl::hWnd() const
{
	return _hWnd;
}
